import { useCallback, useRef, useState } from "react";
import { getTargetElement } from "./get-target-element";
import { TypeOf } from "./type-of";
import { useEventListener } from "./use-event-listener";
import { useMutationObserver } from "./use-mutation-observer";
import { useEffectWithTarget } from "./use-effect-with-target";

const sizeParser = (size) => {
  if (TypeOf.isNumber(size)) {
    return size;
  }
  if (TypeOf.isString(size)) {
    return parseInt(size.replace("px", ""));
  }
  return 0;
};

/**
 * useSize 获取元素宽高
 * 支持 静态/动态测量
 * @param {*} target 支持 React.MutableRefObject<T> | Element | () => Element
 * @returns 宽高对象
 */
const useSize = (target: any) => {
  const [size, setSize] = useState({ width: 0, height: 0 });
  const sizeRef = useRef(null) as any;

  const getSize = useCallback(() => {
    const el = getTargetElement(target);
    if (!el) return;
    const sz = getComputedStyle(el);
    const sizeValue = {
      width: sizeParser(sz.width),
      height: sizeParser(sz.height),
    };
    if (
      sizeRef.current?.width != sizeValue.width ||
      sizeRef.current?.height != sizeValue.height
    ) {
      setSize(sizeValue);
      sizeRef.current = { ...sizeValue };
    }
  }, [target]);

  useMutationObserver(
    (mutationList) => {
      for (const mutation of mutationList) {
        if (mutation.type === "attributes") {
          getSize();
        }
      }
    },
    target,
    { attributes: true, subtree: true }
  );

  useEventListener("resize", getSize, {
    target: window,
  });

  useEffectWithTarget(
    () => {
      target && getSize();
    },
    [],
    target
  );

  return size;
};

export { useSize };
